<@pp.dropOutputFile />
<#import "../lib/function.ftl" as fun/>
<#list dalgen.daos as dao>
    <@pp.changeOutputFile name = "/main/java/${dao.classPath}/${dao.className}.java" />
package ${dao.packageName};

import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
import com.google.common.collect.Lists;
import javax.annotation.Resource;
<#list dao.importLists as import>
import ${import};
</#list>
<#if dalgen.config.getExtParam("updateBatchSize")??>
    <#assign updateBatchSize=dalgen.config.getExtParam("updateBatchSize")/>
<#else>
    <#assign updateBatchSize=200/>
</#if>
/**
* The Table ${dao.tableName!}.
* ${dao.desc!}
*/
<#if dalgen.config.getExtParam("Repository") == "true">@Repository</#if>
public class ${dao.className}{

    @Autowired
    <#if dalgen.dataSourceConfig?? && dalgen.dataSourceConfig.sessionFactory??>
    @Resource(name = "${dalgen.dataSourceConfig.sessionFactory}")
    </#if>
    private  SqlSessionFactory sqlSessionFactory;
    @Autowired
    private ${dao.doMapper.className} ${dao.doMapper.className?uncap_first};

    <#list dao.motheds as method>
        <#if method.databaseId??>
        <#else>
    <#if method.cursor?? && method.cursor=="true">
    public MyBatisCursorItemReader<${fun.CursorTypeClass(method)}> ${method.name}ItemReader(<#list  method.params as param><#if param_index gt 0>,</#if>${param.paramType!} <#assign pagingParam = param.param/>${param.param}</#list>){
        MyBatisCursorItemReader<${fun.CursorTypeClass(method)}> reader = new MyBatisCursorItemReader<>();
        Map${"<"}String,Object${">"}   map    = new LinkedHashMap<>();
        <#list  method.params as param>
        map.put("${param.param}",${param.param});
        </#list>
        reader.setQueryId("${dao.doMapper.packageName}.${dao.doMapper.className}.${method.name}");
        reader.setSqlSessionFactory(sqlSessionFactory);
        reader.setParameterValues(map);
        return reader;
    }
    </#if>
    <#if method.stream?? && method.stream=="true">
    public <T,R> MyBatisStreamItemReader<T,R> ${method.name}StreamReader(<#list  method.params as param><#if param_index gt 0>,</#if><#if param_index !=method.params?size-1> ${param.paramType!} ${param.param}</#if></#list>Function<T, R> function){
        MyBatisStreamItemReader<T,R> reader = new MyBatisStreamItemReader<>(function);
        Map${"<"}String,Object${">"}   map    = new LinkedHashMap<>();
        <#list  method.params as param>
        <#if !param.paramType?starts_with("ResultHandler")>
        map.put("${param.param}",${param.param});
        </#if>
        </#list>
        reader.setQueryId("${dao.doMapper.packageName}.${dao.doMapper.className}.${method.name}");
        reader.setSqlSessionFactory(sqlSessionFactory);
        reader.setParameterValues(map);
        return reader;
    }
    </#if>
    <#-- 预编译模式批量插入更新 -->
    <#if method.batch?? && method.batch=="true">
    public int batch${method.name?cap_first}(<#list  method.params as param><#if param_index gt 0>,</#if><#if param.paramType==dao.aDo.className>List<${param.paramType!}> datas <#else >${param.paramType!} ${param.param}</#if> </#list>){
        if(datas==null || datas.size()==0){
            return 0;
        }
        int dataSize = datas.size();
        SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        try{
            ${dao.doMapper.className} mapper = batchSqlSession.getMapper(${dao.doMapper.className}.class);
            for(int i=0 ; i < dataSize ; i++){
                ${dao.aDo.className!} data = datas.get(i);
                mapper.${method.name}(<#list  method.params as param><#if param_index gt 0>,</#if><#if param.paramType==dao.aDo.className>data<#else >${param.param}</#if> </#list>);
            }
            // 非事务环境下强制commit，事务情况下该commit相当于无效
            batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
        } catch (Exception e) {
            batchSqlSession.rollback();
            throw new RuntimeException(e);
        } finally {
            batchSqlSession.close();
        }
        return dataSize;
    }
    </#if>

    <#if method.kvMap?? && method.kvMap != "false">
     /**
     * desc:${method.desc!method.name!}.<br/>
        <#list  method.params as param>
     * @param ${param.param} ${param.param}
        </#list>
     * @return ${fun.methodClass(method)}
     */
    <#if method.deprecated??&&method.deprecated=="true">@Deprecated</#if>
    public ${method.returnClass} ${method.name}List(<#list  method.params as param><#if param_index gt 0>,</#if>${param.paramType!} <#assign pagingParam = param.param/>${param.param}</#list>){
        <#if method.returnClass != "void">return </#if>${dao.doMapper.className?uncap_first}.${method.name}(<#list  method.params as param><#if param_index gt 0>, </#if>${param.param}</#list>);
    }
    </#if>
    /**
     * desc:${method.desc!method.name!}.<br/>
        <#list  method.params as param>
     * @param ${param.param} ${param.param}
        </#list>
     * @return ${fun.methodClass(method)}
     */
    <#if method.deprecated??&&method.deprecated=="true">@Deprecated</#if>
    public ${fun.methodClass(method)} ${method.name}(<#list  method.params as param><#if param_index gt 0>,</#if>${param.paramType!} <#assign pagingParam = param.param/>${param.param}</#list>){
    <#if method.listLimit??><#if !method.name?starts_with("insert") && method.params?size==1><#list  method.params as param><#if param.paramType?starts_with("List<")>
    if(${param.param}!=null && ${param.param}.size()>${method.listLimit}){throw new RuntimeException("${param.param} 超出${method.listLimit}长度限制");}
    </#if></#list></#if></#if>
    <#if method.pagingFlag == "true">
        <#if method.pagingCustomFlag == "true">
        int total = ${dao.doMapper.className?uncap_first}.${method.pagingCntOperation}(<#list  method.params as param><#if param_index gt 0>, </#if>${param.param}</#list>);
        <#else >
        int total = ${dao.doMapper.className?uncap_first}.${method.name}Count(<#list  method.params as param><#if param_index gt 0>, </#if>${param.param}</#list>);
        </#if>
        if(total>0){
            ${pagingParam}.setDatas(${dao.doMapper.className?uncap_first}.${method.name}Result(<#list  method.params as param><#if param_index gt 0>, </#if>${param.param}</#list>));
        }else{
            ${pagingParam}.setDatas(new ArrayList());
        }
        ${pagingParam}.setTotal(total);
        return ${pagingParam};
    <#elseif method.kvMap?? && method.kvMap == "true">
        ${fun.methodClass(method)} result = new LinkedHashMap();
        ${method.returnClass} resultList = ${dao.doMapper.className?uncap_first}.${method.name}(<#list  method.params as param><#if param_index gt 0>, </#if>${param.param}</#list>);
        if(resultList!=null && !resultList.isEmpty()){
            for(${fun.fanType2Type(method.returnClass)} entity:resultList){
                <#if method.mapV??>
                result.put(entity.get${method.mapK}(),entity.get${method.mapV}());
                <#else >
                result.put(entity.get${method.mapK}(),entity);
                </#if>
            }
        }
        return result;
    <#elseif method.kvMap?? && method.kvMap == "list">
        ${fun.methodClass(method)} result = new LinkedHashMap();
        ${method.returnClass} resultList = ${dao.doMapper.className?uncap_first}.${method.name}(<#list  method.params as param><#if param_index gt 0>, </#if>${param.param}</#list>);
        if(resultList!=null && !resultList.isEmpty()){
            for(${fun.fanType2Type(method.returnClass)} entity:resultList){
                <#if method.mapV??>
                List<${method.mapVType}> vList =  result.get(entity.get${method.mapK}());
                <#else >
                List<${fun.fanType2Type(method.returnClass)}> vList =  result.get(entity.get${method.mapK}());
                </#if>
                if(vList == null){
                    vList = new ArrayList();
                    result.put(entity.get${method.mapK}(),vList);
                }
                <#if method.mapV??>
                vList.add(entity.get${method.mapV}());
                <#else >
                vList.add(entity);
                </#if>
            }
        }
        return result;
    <#elseif method.kvMap?? && method.kvMap == "set">
        ${fun.methodClass(method)} result = new LinkedHashMap();
        ${method.returnClass} resultList = ${dao.doMapper.className?uncap_first}.${method.name}(<#list  method.params as param><#if param_index gt 0>, </#if>${param.param}</#list>);
        if(resultList!=null && !resultList.isEmpty()){
        for(${fun.fanType2Type(method.returnClass)} entity:resultList){
            <#if method.mapV??>
            Set<${method.mapVType}> vSet =  result.get(entity.get${method.mapK}());
            <#else >
            Set<${fun.fanType2Type(method.returnClass)}> vSet =  result.get(entity.get${method.mapK}());
            </#if>
            if(vSet == null){
                vSet = new HashSet();
                result.put(entity.get${method.mapK}(),vSet);
            }
            <#if method.mapV??>
            vSet.add(entity.get${method.mapV}());
            <#else >
            vSet.add(entity);
            </#if>
            }
        }
        return result;
    <#else>
        <#if method.name == "insertBatch" ||method.name?starts_with("insertBatch") || method.name == "updateBatch" || method.name?starts_with("updateBatch")>
        int cnt = 0;
        if(list!=null && list.size()>0){
            if(list.size()>${updateBatchSize}){
                <#list  method.params as param><#if param.param = "list"><#assign ptype =param.paramType/></#if></#list>
                List<${ptype}> partition = Lists.partition(list, ${updateBatchSize});
                for (${ptype} _list : partition) {
                  cnt += ${dao.doMapper.className?uncap_first}.${method.name}(<#list  method.params as param><#if param_index !=0>,</#if><#if param.param = "list">_list<#else >${param.param}</#if></#list>);
                }
            }else{
                cnt += ${dao.doMapper.className?uncap_first}.${method.name}(<#list  method.params as param><#if param_index !=0>,</#if>${param.param}</#list>);
            }
        }
        return cnt;
        <#else>
        <#if method.returnClass != "void">return </#if>${dao.doMapper.className?uncap_first}.${method.name}(<#list  method.params as param><#if param_index gt 0>, </#if>${param.param}</#list>);
        </#if>
    </#if>
    }
        </#if>
    </#list>
}
</#list>
